import z from "zod";
import type { ReportInsert } from "../schemas/reports";
import type { TestInsert } from "../schemas/tests";
import type { Summary, TaskLocator, Test } from "../types/allure";
import { logger } from "./logger";

type Package = {
  uid: string;
  children?: Package[];
};

export const PackageSchema: z.ZodType<Package> = z.lazy(() =>
  z.object({
    uid: z.string(),
    children: z.array(PackageSchema).optional(),
  }),
);

export type ReportTest = { uid: string; reportId: string };

export function getTestsFromPackages(reportId: string, node: Package): ReportTest[] {
  if (!node.children?.length) {
    return [{ uid: node.uid, reportId }];
  }
  return node.children.flatMap((child) => getTestsFromPackages(reportId, child));
}

function getBaseUrl(task: TaskLocator) {
  task.url = task.url.endsWith("/") ? task.url.slice(0, -1) : task.url;
  if (task.name && task.number) {
    return `${task.url}/${task.name}/${task.number}/`;
  } else {
    return `${task.url}`;
  }
}

export async function getReportSummary(task: TaskLocator): Promise<ReportInsert> {
  const baseUrl = getBaseUrl(task);
  logger.info(`Getting allure report from ${baseUrl}`);
  const response = await fetch(`${baseUrl}widgets/summary.json`);
  if (!response.ok) {
    throw new Error("failed to fetch summary");
  }
  const data = await response.json();
  const summary = data as Summary;
  return {
    name: task.name ?? "unkown",
    number: task.number ?? 0,
    summary,
  };
}

export async function getAllTests({ reportId, task }: { reportId: string; task: TaskLocator }) {
  // https://chaocwu.github.io/pytest-template/14/data/packages.json
  const baseUrl = getBaseUrl(task);
  const response = await fetch(`${baseUrl}/data/packages.json`);
  if (!response.ok) {
    throw new Error("failed to fetch packages");
  }
  const data = await response.json();
  const packages = data as Package;
  const tests = getTestsFromPackages(reportId, packages);
  const testsInsert: TestInsert[] = [];
  for (const test of tests) {
    // https://chaocwu.github.io/pytest-template/14/data/test-cases/3fceca2eac8915b2.json
    const response = await fetch(`${baseUrl}data/test-cases/${test.uid}.json`);
    if (!response.ok) {
      throw new Error(`failed to fetch test case: ${test.uid}`);
    }
    const data = await response.json();
    const allureTest = data as Test;
    testsInsert.push({ ...allureTest, reportId });
  }
  return testsInsert;
}
